//
//  CBPeripheral.m
//  CCBluetooth
//
//  Created by zjh on 2021/8/31.
//

#import "CCPeripheral.h"
#import "CCCommandQueue.h"
#define STANDARD_LENGTH 20
@interface CCPeripheral() <CCCommandQueueDelegate>
@property (nonatomic,strong) dispatch_semaphore_t lock;
@property (nonatomic,strong) CCCommandQueue *commandQueue;
@end
static BOOL logEnabled = NO;
@implementation CCPeripheral
+ (void)setLogEnabled:(BOOL)bFlag {
    logEnabled = bFlag;
}

- (id)initWithPeripheral:(CBPeripheral *)peripheral {
    if (self = [super init]) {
        self.name = peripheral.name;
        self.uuid = peripheral.identifier.UUIDString;
        self.peripheral = peripheral;
        self.maxWriteLength = STANDARD_LENGTH;
        self.services = [[NSMutableArray alloc] init];
        self.listenCharacteristices = [[NSMutableArray alloc] init];
        self.commandQueue = [[CCCommandQueue alloc] init];
        self.commandQueue.delegate = self;
        self.lock = dispatch_semaphore_create(1);
    }
    return self;
}

- (BOOL)checkDLE {
    if (@available(iOS 9, *)) {
        _maxWriteLength = [_peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithResponse];
    }
    return _maxWriteLength > STANDARD_LENGTH;
}

- (BOOL)listenForService:(NSString *)serviceUUID characteristic:(NSString *)charactaristicUUID {
    BOOL result = NO;
    dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
    CBCharacteristic *characteristic = [self findCharacteristic:serviceUUID characteristic:charactaristicUUID];
    if (characteristic && !characteristic.isNotifying) {
        [self addListenForCharacteristic:charactaristicUUID];
        [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];
        result = YES;
    }else if(characteristic){
        [self addListenForCharacteristic:charactaristicUUID];
        result = YES;
    }
    dispatch_semaphore_signal(self.lock);
    return result;
}

- (BOOL)removeListenForService:(NSString *)serviceUUID characteristic:(NSString *)charactaristicUUID {
    BOOL result = NO;
    dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
    CBCharacteristic *characteristic = [self findCharacteristic:serviceUUID characteristic:charactaristicUUID];
    if (characteristic && characteristic.isNotifying) {
        [self removeListenForCharacteristic:charactaristicUUID];
        [self.peripheral setNotifyValue:NO forCharacteristic:characteristic];
        result = YES;
    }else if(characteristic){
        [self removeListenForCharacteristic:charactaristicUUID];
        result = YES;
    }
    dispatch_semaphore_signal(self.lock);
    return result;
}

- (void)clearListen {
    dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
    for (NSString *uuid in self.listenCharacteristices.copy) {
        CBCharacteristic *characteristic = [self findCharacteristic:uuid];
        if (characteristic && characteristic.isNotifying) {
            [self.peripheral setNotifyValue:NO forCharacteristic:characteristic];
        }
        [self removeListenForCharacteristic:uuid];
    }
    dispatch_semaphore_signal(self.lock);
}

- (void)writeCommand:(CCCommand *)command {
    [self.commandQueue addCommand:command];
}

- (void)addListenForCharacteristic:(NSString *)charactaristicUUID {
    [self.listenCharacteristices removeObject:charactaristicUUID];
    [self.listenCharacteristices addObject:charactaristicUUID];
#ifdef DEBUG
    if (logEnabled) {
        NSLog(@"添加订阅特征值：%@",charactaristicUUID);
    }
#endif
}

-(void)removeListenForCharacteristic:(NSString *)charactaristicUUID {
#ifdef DEBUG
    if (logEnabled) {
        NSLog(@"移除订阅特征值：%@",charactaristicUUID);
    }
#endif
    [self.listenCharacteristices removeObject:charactaristicUUID];
}

#pragma mark CCCommandQueueDelegate
- (void)commandQueue:(CCCommand *)command {
    CBCharacteristic *characteristic = [self findCharacteristic:command.characteristicUUID];
    if (characteristic) {
#ifdef DEBUG
        if (logEnabled) {
            NSLog(@"App发送指令：%@",command.data);
        }
#endif
        [self.peripheral writeValue:command.data forCharacteristic:characteristic type:command.withResponse ? CBCharacteristicWriteWithResponse : CBCharacteristicWriteWithoutResponse];
    }else{
#ifdef DEBUG
        if (logEnabled) {
            NSLog(@"蓝牙设备找不到特征值（通道）");
        }
#endif
    }
}

- (CBCharacteristic *)findCharacteristic:(NSString *)serviceUUID
                          characteristic:(NSString *)charactaristicUUID {
    CBService *service = [self findServiceForUuid:serviceUUID];
    if (service) {
        for (CBCharacteristic *character in service.characteristics) {
            if ([character.UUID isEqual:[CBUUID UUIDWithString:charactaristicUUID]]) {
                return character;
            }
        }
    }
    return nil;
}

- (CBService *)findServiceForUuid:(NSString *)serviceUUID {
    for (CBService *service in self.peripheral.services) {
        if ([service.UUID isEqual:[CBUUID UUIDWithString:serviceUUID]]) {
            return service;
        }
    }
    return nil;
}

- (CBCharacteristic *)findCharacteristic:(NSString *)charactaristicUUID {
    for (CBService *service in self.peripheral.services) {
        for (CBCharacteristic *character in service.characteristics) {
            if ([character.UUID isEqual:[CBUUID UUIDWithString:charactaristicUUID]]) {
                return character;
            }
        }
    }
    return nil;
}

@end
